#include "Noyau/Rayon.hpp"
#include "Noyau/Camera.hpp"
#include "Noyau/Environnement.hpp"
#include "Noyau/Lib.hpp"

#include "Algebre/Coord.hpp"
#include "Algebre/Vecteur.hpp"

#include "Formes/LibForm.hpp"

#include "Image/ImageFilePPM.hpp"
#include "Image/ImageFilePng.hpp"
#include "Image/ImageFileJpeg.hpp"
#include "Image/ImageFileTiff.hpp"
#include "Image/ReadImageFile.hpp"

#include "Lumieres/Source.hpp"

#include "Materiaux/Materiau.hpp"
#include "Materiaux/Carreaux.hpp"


#include "Utils/borne.hpp"
#include "Utils/StatusCode.hpp"
#include "Utils/debugstreams.hpp"

#include "Xml/Parser.hpp"
#include "Xml/InterpreteXML.hpp"

#include <iostream>
#include <iomanip>
#include <sstream>
#include <stdio.h>

#include <boost/assign/list_of.hpp>

using namespace std;
using namespace boost::assign;

bool format_xml(string output) // regarde si le fichier possede l extension xml
{
    if (output.size()<5) // si le nom est plus petit que 4 lettres
        return false;    // on renvoi false
    int j=output.find(".xml");
    if (j!=-1)
        return true;
    else
        return false;
}

int cherche_format(string output) // permet de lire l'extension
{
    if (output.size()<5)
        return -1;
    int format;
    int p=output.find(".jpg");
    if (p!=-1)
        format=0;
    else
    {
        p=output.find(".jpeg");
        if (p!=-1)
            format=0;
        else
        {
            p=output.find(".png");
            if (p!=-1)
                format=1;
            else
            {
                p=output.find(".tif");
                if (p!=-1)
                    format=2;
                else
                {
                    p=output.find(".tiff");
                    if (p!=-1)
                        format=2;
                    else
                    {
                        p=output.find(".ppm");
                        if (p!=-1)
                            format=3;
                        else
                        {
                            format=-1;
                        }
                    }
                }
            }
        }
    }
    return format;
}

int main (int argc, char * const argv[])
{
    string input;
    string output;
    unsigned int qualite( 97 );

    string tmp;
    // traitement des parametres passe a l executable
    for (int i(1); i < argc; i++)
    {
        tmp = string( argv[i] );
        if ( tmp == "-i" )
        {
            i++;
            input = argv[i];
        }
        else if ( tmp == "-o" )
        {
            i++;
            output = argv[i];
        }
        else if ( tmp == "-q" )
        {
            i++;
            stringstream ss( argv[i] );
            ss >> qualite;
        }
    }

    // affichage du titre
    cout << setfill('#') << setw(54) << '#' << endl;
    cout << '#' << setfill(' ') << setw(53) << '#' << endl;
    cout << '#' << setw(28) << "RJRay" << setw(25) << '#' << endl;
    cout << '#' << setw(30) << "Beta 1.0" << setw(23) << '#' << endl;
    cout << '#' << setfill(' ') << setw(53) << '#' << endl;
    cout << setfill('#') << setw(54) << '#' << endl;
    cout << endl << endl;

    int format=0; // numerote le format choisi par l'utilisateur par défaut vaut zero

    if (format_xml(input))
    {
        cout << "On utilise " << input << " pour générer la scène" << endl;
        format=cherche_format(output);
        if (format==0) // cas du Jpeg. Il faut alors demander la qualite
        {
            qualite = borne( qualite, 0u, 100u ); // on borne au cas ou
        }
        if (format!=-1) // cas ou on a un format valide
        {
            cout << "L'image sera sauvée dans " << output << endl;
            bool OK;

            Parser p( input );

            StatusCode sc( p . chargerFichier() );
            if ( ! sc )
            {
                error() << "Problème de lecture du fichier" << endreq;
                return 1;
            }
            sc = p.lireDocument();
            if ( ! sc )
            {
                error() << "Problème de lecture" << endreq;
                return 1;
            }
            Environnement *scene;
            Camera *cam;
            vector< const ElementDOM* > information;
            sc = p . getStructureFichier( information );
            cam = lireCamera( information, OK );
            if ( ! OK )
            {
                error() << "Ne peut pas charger la caméra" << endreq;
                return 1;
            }
            // 		      else
            // 			cout << "Caméra OK" << endl;
            scene = lireEnvironnement( information, OK );
            if ( ! OK )
            {
                error() << "Ne peut pas charger l'environnement"
                        << endreq;
                return 1;
            }
            // 		      else
            // 			cout << "Environnement OK" << endl;
            cam -> env( scene );
            try
            {
                //p.extract(image,cam, kBlack); // les valeurs par defaut vont etre modifier
                cam->genereImage(); // on lance les rayon
                // on cherche le format choisi et on ecrit le fichier
                if (format==0)
                {
                    ImageFileJpeg mon_image(cam->film(),output,qualite);
                    mon_image.affiche();
                }
                if (format==1)
                {
                    ImageFilePng mon_image(cam->film(),output);
                    mon_image.affiche();
                }
                if (format==2)
                {
                    ImageFileTiff mon_image(cam->film(),output);
                    mon_image.affiche();
                }
                if (format==3)
                {
                    ImageFilePPM mon_image(cam->film(),output);
                    mon_image.affiche();
                }
            }
            catch(Erreur &err) // en cas d'erreur dans le fichier xml
            {
                cout << "Consulter Syntax_Error_XML.txt pour plus d info" << endl;
                err.ecrire("Syntax_Error_XML.txt");
            }
            // on rend la memoire au systeme
            cout << (char)7;
            //delete image;
            delete cam;
            delete scene;
        }
        else
        {
            cout << "Format de fichier inconnu" << endl;
        }
    }

    return 0;
}
